[DO NOT MERGE] Yanwen/dev 1.3 - #11
Conversation
…timization Full snapshot of the WMMA/SDPA speckit workstream's planning docs and speckit scaffolding as of 2026-07-08, including specs 016-023 that were still uncommitted on quant-perf-optimization. quant-perf-optimization itself is left untouched -- this is a copy, not a move.
… to dev Ports the M5 EVT1 WMMA coopmat path from quant-perf-optimization into dev/executorch: linear_qw_coopmat (4w) and linear_dq8ca_qw_coopmat (8da4w) shaders, SDPA QK^T/AV coopmat shaders, GemmCoopmat dispatch, and the QuantizedLinear.cpp/SDPA.cpp coopmat eligibility gates. Adds supports_int8_cooperative_matrix() (Adapter/Device) needed to gate the 8da4w int8 coopmat path. Also fixes two storage-override bugs found while validating the port on device (buffer-storage export was silently collapsing to texture, so coopmat never dispatched): - tag_memory_meta_pass.py/utils.py: force_fp16 unconditionally forced ANY_TEXTURE, defeating any BUFFER storage_type_override. - vulkan_partitioner.py: ET_VK_FORCE_BUFFER env var (used by the canonical export_quant.sh) was never wired to storage_type_override in dev at all. Dropped Q4gswLinear.cpp/h from the port -- confirmed dead code (its op is unreachable from any real export path; the real 4w coopmat dispatch lives in QuantizedLinear.cpp). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…sensitive kernel picks TextLLMRunner::warmup() built a fresh GenerationConfig without copying num_bos/num_eos from the real call, so warmup always tokenized with num_bos=0 regardless of what the caller passed via --num_bos. This made warmup's prefill exactly one token shorter than the real run's, and since warmup executes first on the same graph, whichever shader a DynamicDispatchNode binds on that first (wrong-shape) call sticks for the node's lifetime -- silently forcing every later dispatch, including the correctly-shaped real run, onto that same choice. Found while validating the M5 EVT1 WMMA coopmat port: the real 2048-token prefill passed every coopmat eligibility check (verified via temporary instrumentation) yet ETDump showed the tiled kernel actually executing. Root cause was warmup's misaligned M=2047 (vs the real run's M=2048) binding the tiled pipeline first. Passing num_bos/num_eos through fixes it end-to-end: linear_q4gsw_coopmat now dispatches for real with --warmup=true (the documented default), no workaround needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…sweep Adds spec-kit docs for sweeping the dq8ca/q4gsw int8 WMMA shader's tile-shape x subgroup-grid x subgroup-size space on M5 EVT1, reusing 022's smart-autotune methodology (analytical pruning -> staged search) re-derived for this shader's own register/shared-memory constraints. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…5 EVT1 Re-confirms dbuf2 as the fastest loop structure for 8da4w (fresh measurement, 6/6 shapes), then sweeps its tile/subgroup geometry via 022's analytical-pruning + staged-search methodology, re-derived for this shader's own int8-MMA constraints (542 legal candidates, not 4w's 642 -- SUBGROUP_SIZE fixed at 64, and WG_TILE_K=64 excluded once found incompatible with this workstream's real group_size=32). Winner: 128x32/K16/1x2/s64 (dbuf2 loop) at 1731.0 GFLOP/s, +2.55% over the shipped 128x64/K32/2x2/s64 config -- 3-run mean, CoV<0.3%, correctness-verified, SPIR-V-confirmed genuine int8 coopmat dispatch. 29/542 candidates (5.4%) measured on hardware, under the 30-cap budget. Side finding: the documented Xclipse PAL subgroup=32 compiler crash did not reproduce on the current driver -- flagged for a follow-up feature (results/subgroup32-reverification.md), not acted on here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63b5ce897a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (group_size % tile_k != 0) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Reject partial quantization groups before coopmat
When K is tile-aligned but not an exact multiple of group_size (for example K=288, group_size=128), this gate still enables the coopmat path. Both add_linear_qw_node and add_linear_dqa_qw_node pass K / group_size as the shader trip count, so integer truncation drops the final partial quantization group and silently omits those input channels; require K % group_size == 0 here or compute a ceil trip count before selecting coopmat.
Useful? React with 👍 / 👎.
| if (p.AType == VK_COMPONENT_TYPE_SINT8_KHR) { | ||
| supports_int8_coopmat = true; |
There was a problem hiding this comment.
Require exact int8 coopmat property match
A device can enumerate VK_COMPONENT_TYPE_SINT8_KHR for AType in a cooperative-matrix property that does not match the linear_dq8ca_q4gsw_coopmat shader's required SINT8 x SINT8 -> SINT32 16x16x16 operation. Marking support from AType alone makes supports_int8_cooperative_matrix() select the int8 coopmat shader on such devices instead of falling back, which can fail pipeline creation or run an unsupported matrix shape; match the full property tuple (B/C/result types, dimensions, and scope) before setting the flag.
Useful? React with 👍 / 👎.
SDPA coopmat (QK^T/AV) was previously opt-in via ET_VK_SDPA_COOPMAT. Per specs/026-sdpa-8da4w-defaults-e2e, drop the opt-in env var so it's enabled by default wherever the existing subgroup/cooperative-matrix capability checks already gate it; ET_VK_DISABLE_COOPMAT remains the shared kill switch with the q4gsw linear coopmat path. Authored with Claude Code.
Redo specs/025's 8da4w tile/subgroup sweep with SUBGROUP_SIZE as a real axis instead of fixed-at-64, per this session's re-verification finding that the documented compiler crash is stale but the axis is shape- dependently incorrect/slower at the shapes checked so far.
Found a real winner: t64x64k16g21s32 (SUBGROUP_SIZE=32) hits 2207.2 GFLOP/s vs specs/025's standing 1736.0 GFLOP/s winner (+27.1%), passing correctness across all 10 representative shapes. Correctness at subgroup=32 is sharply tile-shape-dependent -- the two shapes prior single-shape probes (025's T014, this session's earlier sg32test check) happened to test are exactly the two worst shapes in a 5-shape spread.
t64x64k16g21s32 wins the isolated microbenchmark (+27.1%) but measures ~7.6% SLOWER end-to-end on Llama 3.2 1B 2048-token prefill (406.8 vs 440.1 tok/s median, 3 runs each, non-overlapping). Recommendation downgraded from productionize_candidate to keep_shipped_baseline. Correctness/legality finding (subgroup=32 doesn't crash the compiler, shape-dependently correct) still stands independent of this result.
Initial Tier-2 check used Llama 3.2 1B (hidden=2048/inter=8192), but the microbenchmark that found the winning config used 8B-shaped GEMMs (K=4096/14336) -- an apples-to-oranges comparison caught on review. Re-ran on the shape-matched 8B model: still slower e2e, but by -2.7% (98.01 vs 100.73 tok/s), not the flawed -7.6% from the 1B run. Recommendation (keep_shipped_baseline) is unchanged, but now on correct evidence.
… with microbenchmark rank Screened+confirmed top-8 candidates by combined specs/025+specs/026 microbenchmark rank against real e2e prefill throughput (Llama 3.1 8B, 2048-token prefill, M5 EVT1). tsweep_t64x32k32g12s64 (microbenchmark rank 4/27) wins e2e at +9.32% over shipped baseline, non-overlapping 3-run confirmation. Both prior features' microbenchmark "winners" (025's #1 and 026's #1) underperform e2e -- 025's own top candidate is the single worst performer of everything measured here. User Story 2 (search extension) correctly skipped since a real winner was found in User Story 1.
…ault Loop structure: dbuf4 -> dbuf2 (dev never received the specs/023 dbuf2 port; porting it was required to apply the tile winner faithfully, since the winner was found and validated at dbuf2). Tile geometry: 128x64/K32/2x2/s64 -> 64x32/K32/1x2/s64 (tsweep_t64x32k32g12s64, specs/027-e2e-tile-sweep). Confirmed on full dev stack (SDPA coopmat default-on, Llama 3.1 8B 8da4w buffer PTE, 2048-token prefill, M5 EVT1, pinned clocks): 131.24 -> 147.65 tok/s, +12.5%, non-overlapping 3-run ranges. This is a real, statistically confirmed end-to-end improvement, not just isolated-kernel GFLOP/s (specs/025's/026's own microbenchmark "winners" turned out to be e2e regressions -- specs/027 exists precisely because of that gap). See specs/027-e2e-tile-sweep/results/dev-branch-production-validation.md for the full validation writeup.
…032 results Covers 07-11 through 07-17: 8da4w-slower-than-4w investigation (024), paused 4w e2e tile sweep pending driver reflash authorization (028), release-1.1/1.2/1.3 4w baseline comparison (029), M41 release/1.3 baseline (030), release/1.3 crash survey with node-threshold workaround (031), and the SUMD driver bisect identifying 69e887275e as the dot4_i32_i8-disabling regression commit, with M5 EVT1 ISA/SPIR-V dumps confirming the quantized coop kernels never declare CooperativeMatrixKHR (032). Also excludes ISA-dump binary extensions (.elf/.tgz/.spv/.disasm/.spvasm) from the NEWLINE linter, which had no prior exposure to these file types.
…lush hypothesis refuted) Bisect narrowed the M5 coopmat segfault to commit 805609f0da; its proposed GL2 cache-flush mechanism was tested and refuted same-day, with the crash further isolated to a likely UAF in ProcessBoundResourcesForCompute.
…at paths test_llama_microbench runs the real e2e dispatch shapes of Llama 3.2 1B/3B and 3.1 8B (2048-token prefill, single-token decode) through the runtime's own shader selection, comparing coopmat against tiled per shape, a forced-tiled reference on the coopmat path's own storage type to isolate algorithm from storage effects, and the SDPA coopmat toggle at the real attention shapes. Correctness gates run by default; --linear/--baseline/ --sdpa/--model= filter the matrix, --list enumerates it. Because dispatch goes through the runtime pick functions, the benchmark automatically measures whatever tile defaults the linked backend ships, and composes with the tsweep variant env toggles where those exist. Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyWujKVd6J6TfrKCUMWNy9
…ess failures, size prefill cache to ctx3072 Fixes from an independent methodology review of the consolidated Llama microbenchmark. The 8da4w rows previously reported op-level time (the activation quantize_and_pack dispatch slipped past the stale quantize_and_pack_4w4c shader filter) while being labeled as kernel time; rows now carry both mean_us (op-level, the e2e-relevant quantity, still feeds the geomeans) and kernel_us (linear shader only, judges the WMMA kernel itself), with op_x/kern_x columns in the report. The correctness gate runs one execute_test_cases() call per case and catches the framework's validation throw, so a numeric failure is recorded and every failing case is listed instead of the first one killing the process. SDPA prefill's KV cache is sized 3072 to match the real ctx3072 PTEs, which allocate the cache at max_context_length even during prefill. Also: the report's fallback annotation now actually prints (the coopmat-filtered lookup made it unreachable; display uses the unfiltered buffer row while speedups/geomeans keep the filter), a DEVICE provenance line records adapter/timestamp-period/subgroup, and the per-model geomean row aligns under its column. First full run on 780M (RADV): 4w coopmat 3.08x geomean, SDPA 2.84x, but 8da4w coopmat is 0.65x -- slower than tiled on this device, kern_x confirming it is the kernel itself rather than quantize overhead. Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Brings the ET_VK_Q4GSW_COOPMAT_VARIANT / ET_VK_DQ8CA_COOPMAT_VARIANT env-var dispatch, the two tsweep shader templates with their compiled variant lists, and the coopmat correctness/perf bench over from yanwen/dev-igpu so the specs/036 sweep toolkit can run on this branch on any device. Shipped default tile geometry is deliberately left at this branch's specs/027 values -- retuned defaults remain a per-device decision made through the sweep protocol, not part of the machinery. Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyWujKVd6J6TfrKCUMWNy9
Replaces the hand-designed sweep rounds of specs/022-035 with a committed, one-command-per-shader pipeline for retuning coopmat tile defaults on any new GPU: device-parametrized legality model, Optuna TPE search with batched yaml-append/rebuild, correctness gate with dispatch proof, interleaved control runs with drift re-baselining, temperature-0 output-hash miscompute detection, and journal-based resume. protocol.md is the operator entry point; contracts/ documents the result schema. Validated on 780M via a specs/035 replay (recovers the known winner) plus a live micro-sweep, and ships the measured verdict that the microbenchmark rank is a trustworthy prefilter on this device (Spearman 0.91 4w / 0.999 8da4w, top-5 recall 1.0) while e2e keeps the final word. Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyWujKVd6J6TfrKCUMWNy9
…ault linear_qw_coopmat.yaml's WG_TILE_N moves 64->128 (M/K/grid/subgroup unchanged) and kQ4gswCoopmatDims in QuantizedLinear.cpp follows, based on specs/036-portable-device-sweep's Optuna-driven tile sweep on M51 (samsung xclipse 970): tsweep_t128x128k16g22s32 beat the prior 128x64/2x2 tile by +6.8%/+7.7%/+10.1% prefill tok/s on 1B/3B/8B respectively, confirmed with no rank flip between sizes. Re-verified through the shipped (non-tsweep-env) code path after porting: 44/44 correctness cases pass, and 3B/8B reproduce the predicted numbers cleanly (359.6 and 168.8 tok/s, <0.4% noise). The sweep toolkit itself only shipped host-local (validated on 780M/RADV); running it on M51 required a new adb/ssh backend (scripts/measure_android.py) plus a --remote hook in sweep.py, since the device is only reachable through an ssh hop to the adb host. Included here along with the run journals, per-token blocklist, and sweep/validation summaries specs/036's own schema calls for committing. Authored with Claude.
Replaces the three fused suite flags with orthogonal ingredient axes so any combination can be selected directly: --suite=linear,sdpa,baseline, --variant=tiled,coopmat (aliases baseline/wmma), --regime=prefill,decode, --warmup/--runs with a --quick preset, and --output=human|machine|both (machine adds SPEEDUP,/GEOMEAN, CSV lines to the streamed RESULT, lines; human prints only the tables). The all-tiled baseline suite drops out automatically when the tiled variant is deselected, and a tiled-only SDPA prefill run now reports unexpected_coopmat if the disable toggle failed. Defaults reproduce the previous full run (201 cases). Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a STORAGE section to the report, built from the baseline suite's forced-tiled rows -- the only place the tiled algorithm runs on buffer storage -- so the storage-type effect can be read directly instead of eyeballing raw rows: prefill compares the tiled shader across storages, decode the _coop gemv shader (force-tiled does not affect the gemv pick). Emits per-site SPEEDUP,storage and per-scheme/regime GEOMEAN,storage lines in machine output. Measured on 780M/RADV: tiled 4w is a uniform ~1.20x faster on buffer across all 12 prefill sites; tiled 8da4w is storage-insensitive (geomean 1.02x). Authored with Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
[PLEASE REMOVE] See CONTRIBUTING.md's Pull Requests for ExecuTorch PR guidelines.
[PLEASE REMOVE] If this PR closes an issue, please add a
Fixes #<issue-id>line.[PLEASE REMOVE] If this PR introduces a fix or feature that should be the upcoming release notes, please add a "Release notes: " label. For a list of available release notes labels, check out CONTRIBUTING.md's Pull Requests.
Test plan
[PLEASE REMOVE] How did you test this PR? Please write down any manual commands you used and note down tests that you have written if applicable.